#ifndef STATEMENTCPP
#define STATEMENTCPP

#include"interpreter.hpp"

printStatement::printStatement(expression* exp){
	this->exp=exp;
}

statement* printStatement::readStatement(parser* p,interpreter* i){
	//current -> print
	int line=i->getCurrentLine();i->next();int l=i->getCurrent();
	while(i->atTail()==false&&i->meetSemicolon()==false)
		i->next();
	if(i->atTail()){
		i->report(line,"missing ;");
		return new statement;
	}
	int r=i->getCurrent()-1;i->next();
	printStatement* ans=new printStatement(
		p->getExpression(l,r)
	);
	return ans;
}

void printStatement::execute(interpreter* i){
	if(exp==nullptr){
		std::cout<<"nil\n";
	}
	else{
		exp->getValue(i)->output();
		std::cout<<"\n";
	}
}

declarationStatement::declarationStatement(std::string varName,expression* exp){
	this->varName=varName;
	this->exp=exp;
}

statement* declarationStatement::readStatement(parser* p,interpreter* i){
	//current -> var
	int line=i->getCurrentLine();i->next();int l=i->getCurrent();
	while(i->atTail()==false&&i->meetEqual()==false&&i->meetSemicolon()==false)
		i->next();
	if(i->atTail()){
		i->report(line,"missing ;");
		return new statement;
	}
	if(i->meetSemicolon()){
		int r=i->getCurrent()-1;
		if(l<r){i->report(line,"too many variables");return new statement;}
		if(l>r){i->report(line,"variable not found");return new statement;}
		i->next();
		return new declarationStatement(
			i->getCurrentLexeme(),
			nullptr
		);
	}
	if(i->meetEqual()){
		int r=i->getCurrent()-1;
		if(l<r){i->report(line,"too many variables");return new statement;}
		if(l>r){i->report(line,"variable not found");return new statement;}
		i->prev();
		std::string tName=i->getCurrentLexeme();
		i->next();i->next();l=i->getCurrent();
		while(i->atTail()==false&&i->meetSemicolon()==false)
			i->next();
		if(i->atTail()){
			i->report(line,"missing ;");
			return new statement;
		}
		r=i->getCurrent()-1;
		i->next();
		return new declarationStatement(
			tName,
			p->getExpression(l,r)
		);
	}
}

void declarationStatement::execute(interpreter* i){
	i->define(this->varName,this->exp->getValue(i));
}

blockStatement::blockStatement(decltype(statements) s){
	this->statements=s;
}

statement* blockStatement::readStatement(parser* p,interpreter* i){
	//current -> {
	int line=i->getCurrentLine();std::vector<statement*> tmp;i->next();
	while(i->atTail()==false&&i->meetRightBrace()==false){
		tmp.push_back((i->getStatement(p)));
	}
	//current -> }
	if(i->atTail()){
		i->report(line,"missing }");
		return new statement();
	}
	i->next();
	return new blockStatement(tmp);
}

void blockStatement::execute(interpreter* i){
	for(auto it:this->statements){
		it->execute(i);
	}
}

expressionStatement::expressionStatement(expression* exp){
	this->exp=exp;
}

statement* expressionStatement::readStatement(parser* p,interpreter* i){
	int line=i->getCurrentLine(),l=i->getCurrent();
	while(i->atTail()==false&&i->meetSemicolon()==false){
		i->next();
	}
	if(i->atTail()){
		i->report(line,"missing ;");
		return new statement();
	}
	int r=i->getCurrent()-1;
	i->next();
	return new expressionStatement(p->getExpression(l,r));
}

void expressionStatement::execute(interpreter* i){
	var* tmp=this->exp->getValue(i);
	DELETE(tmp);
}

#endif